package bod.engine;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

import bod.Images;
import bod.engine.map.Map;
import bod.engine.map.blocks.Block;
import bod.engine.objs.House;
import bod.engine.objs.Object2D;
import bod.engine.objs.Player;
import bod.engine.objs.Torch;
import bod.gui.Screen;

public class Engine {

	private static boolean				running;
	private static int					gravity;
	private static Map					map;
	private static ArrayList<Object2D>	objects;
	private static ArrayList<Object2D>	addsQueue;
	private static ArrayList<Object2D>	deleteQueue;
	private static Environment			environment;
	private static Player				player;

	public static void createObject(Object2D obj) {
		addsQueue.add(obj);
	}

	public static Block getBlock(int x, int y) {
		return map.getBlock(x, y);
	}

	public static int getGravity() {
		return gravity;
	}

	public static int getMapWidth() {
		return map.getWidth();
	}

	public static int getMapHeight() {
		return map.getHeight();
	}

	public static int getSeason() {
		return environment.getSeason();
	}

	public static int getWind() {
		return environment.getWind();
	}

	public static boolean isDay() {
		return environment.isDay();
	}

	public static void removeObject(Object2D obj) {
		deleteQueue.add(obj);
	}

	public static void setBlock(Block block, int x, int y) {
		map.setBlock(block, x, y);
	}

	public static void initialize() {
		gravity = 16;
		map = new Map();
		objects = new ArrayList<Object2D>();
		addsQueue = new ArrayList<Object2D>();
		deleteQueue = new ArrayList<Object2D>();
		environment = new Environment();
		for (int i = 0; i < 8; i++) {
			createObject(new Torch(36 + i * 256, map.getHeight() - 256));
		}
		createObject(new House(600, 200));
		player = new Player(47 * 16, 0 * 16);
		createObject(player);
		running = true;
	}

	public static void tick() {
		if (running) {
			map.tick();
			for (Object2D obj : objects) {
				obj.tick();
			}
			for (Object2D obj : addsQueue) {
				objects.add(obj);
			}
			addsQueue.clear();
			for (Object2D obj : deleteQueue) {
				objects.remove(obj);
			}
			deleteQueue.clear();
			environment.tick();
		}
	}

	public static void draw(Graphics g) {
		if (running) {
			int w = Screen.getWidth();
			int h = Screen.getHeight();
			g.setColor(Color.black);
			g.fillRect(0, 0, w, h);
			int cx = w / 2 - player.getX();
			int cy = h / 2 - player.getY();
			Block[][] blocks = map.getBlocks();
			for (int x = 0; x < blocks.length; x++) {
				for (int y = 0; y < blocks[x].length; y++) {
					Block block = blocks[x][y];
					int bx = x * Block.size + cx;
					int by = y * Block.size + cy;
					if (bx > -Block.size && bx < w && by > -Block.size
							&& by < h) {
						g.drawImage(block.getBack(), bx, by, null);
						g.drawImage(block.getImage(), bx, by, null);
					}
				}
			}
			for (Object2D obj : objects) {
				int ox = obj.getX() + cx;
				int oy = obj.getY() + cy;
				int ow = obj.getWidth();
				int oh = obj.getHeight();
				if (ox > -ow && oy > -oh && ox < w && oy < h) {
					g.drawImage(obj.getImage(), ox, oy, ow, oh, null);
				}
			}
			for (int x = 0; x < map.getWidth(); x += Block.size) {
				for (int y = 0; y < map.getHeight(); y += Block.size) {
					int dx = x + cx;
					int dy = y + cy;
					if (dx > -Block.size && dy > -Block.size && dx < w
							&& dy < h) {
						int d = environment.getDarkness();
						if (d > 0) {
							g.setColor(new Color(0, 0, 0, d < 255 ? d : 255));
							g.fillRect(dx, dy, Block.size, Block.size);
						}
					}
				}
			}
			if (Math.random() < 0.1) {
				a++;
			}
			if (a > 15) {
				a = 0;
			}
			g.drawImage(Images.hlth[a], 32, 32, null);
		}
	}

	private static int	a;

	public static void keyPressed(int key) {
		if (running) {
			switch (key) {
				case KeyEvent.VK_W:
					player.jump();
					break;
				case KeyEvent.VK_A:
					player.left(true);
					break;
				case KeyEvent.VK_D:
					player.right(true);
					break;
				case KeyEvent.VK_X:
					Random r = new Random();
					int rx = r.nextInt(map.getWidth());
					int ry = r.nextInt(map.getHeight() / 4);
					map.setBlock(new Block(Map.water, rx, ry), rx, ry);
					break;
			}
		}
	}

	public static void keyReleased(int key) {
		if (running) {
			switch (key) {
				case KeyEvent.VK_A:
					player.left(false);
					break;
				case KeyEvent.VK_D:
					player.right(false);
					break;
			}
		}
	}

	public static void mousePressed(int x, int y) {
	}

	public static void mouseReleased(int x, int y) {
	}

	public static void mouseMoved(int x, int y) {
	}

}